package com.lsec.springbootinit.config;

import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;

import java.time.Duration;
import java.util.concurrent.TimeUnit;


/**
 * spring cache 管理器配置
 *
 * @author Cherry
 * @date 2023-03-03 14:42
 */
@Configuration
public class CacheManagerConfig {

    public static final String MANAGER_5_MIN = "5MinuteCacheManager";
    public static final String MANAGER_10_SEC = "10SecondCacheManager";
    public static final String MANAGER_REDIS_10_SEC = "redisCacheManager";

    @Autowired
    private LettuceConnectionFactory lettuceConnectionFactory;


    /**
     * 配置缓存管理器
     *
     * @return 缓存管理器
     */
    @Bean(MANAGER_10_SEC)
    @Primary
    public CacheManager tenSecondCacheManager() {

        CaffeineCacheManager cacheManager = new CaffeineCacheManager();

        cacheManager.setCaffeine(Caffeine.newBuilder()
                // 设置最后一次写入或访问后经过固定时间过期
                //.expireAfterAccess(10, TimeUnit.SECONDS)
                .expireAfterWrite(10, TimeUnit.SECONDS)
                // 初始的缓存空间大小
                .initialCapacity(10000)
                .recordStats()
                // 缓存的最大条数
                .maximumSize(20000));
        return cacheManager;
    }

    /**
     * 配置缓存管理器
     *
     * @return 缓存管理器
     */
    @Bean(MANAGER_5_MIN)
    public CacheManager fiveMinuteCacheManager() {

        CaffeineCacheManager cacheManager = new CaffeineCacheManager();

        cacheManager.setCaffeine(Caffeine.newBuilder()
                // 设置最后一次写入或访问后经过固定时间过期
                //.expireAfterAccess(60, TimeUnit.SECONDS)
                .expireAfterWrite(5, TimeUnit.MINUTES)
                // 初始的缓存空间大小
                .initialCapacity(10000)
                .recordStats()
                // 缓存的最大条数
                .maximumSize(20000));
        return cacheManager;
    }

    /**
     * redis Cache
     * @return RedisCacheManager
     * 设置序列化的地方 用new GenericJackson2JsonRedisSerializer() 可以解决一切问题, 缺点是redis中有路径记录
     *
     * 用new Jackson2JsonRedisSerializer(xxxx.class) 解决单实体的问题  但是每个都要写一个实体对应的序列化器 , list的问题没法解决
     */
    @Bean(MANAGER_REDIS_10_SEC)
    public RedisCacheManager redisCacheManager(){

        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                // 设置时间
                .entryTtl(Duration.ofSeconds(1500))
                //设置序列化器
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));

        return RedisCacheManager.builder(lettuceConnectionFactory)
                .cacheDefaults(config)
                .build();
    }
}
